<?php

namespace App\Web\Model;

use App\Facades\Captcha;
use App\Service\Mailer;
use App\Service\ExternalAPI\CaseResumeApi;
use App\Service\Sms;
use App\Web\Facades\UserAuth;
use App\Web\Model\User as UserModel;
use App\Web\Model\Login as LoginModel;
use EchoPHP\Facades\Db;
use EchoPHP\Facades\Log;
use EchoPHP\Facades\Redis;
use EchoPHP\Validator\Validator;

Class Operator extends Model {
    protected $codeCount = 8;
    protected $title = [['key' => 'name', 'title' => '顾问工作量情况'], ['key' => 'code1', 'title' => '加入项目'], ['key' => 'code2', 'title' => '电话沟通'], ['key' => 'code3', 'title' => '简历推荐'],
        ['key' => 'code4', 'title' => '简历反馈'], ['key' => 'code5', 'title' => '现场面试'], ['key' => 'code6', 'title' => 'offer'], ['key' => 'code7', 'title' => '入职'],
        ['key' => 'code8', 'title' => '保证期']];

    /**
     * Notes:修改用户信息
     * @param $oprId
     * @param $params
     * @return array
     * @throws \Exception
     */
    /*public function editInfo($oprId, $params) {
        $rule = [
            'email' => [
                'email', 'maxLength' => 100
            ],
            'mobilephone|联系方式' => [
                'telPhone', 'maxLength' => 20
            ],
            'position|职位' => [
                'maxLength' => 100
            ],
            'department|部门' => [
                'maxLength' => 100
            ],
        ];
        $validate = new Validator($rule);

        $result = $validate->validate($params);

        if (!$result) {
            return [
                'status' => false,
                'message' => '字段校验失败,请检查输入格式',
                'validateFailure' => $validate->getErrors()
            ];
        }

        $sql = 'UPDATE User SET email=?,mobilephone=?,position=?,department=?,updatedate=Now() WHERE userid=?';
        $var = [
            $params['email'], $params['mobilephone'], $params['position'], $params['department'], $oprId
        ];
        $setResult = Db::update($sql, $var);
        if (!$setResult) {
            return ['status' => false, 'message' => '保存失败'];
        }

        return ['status' => true, 'message' => '保存成功'];
    }*/

    /**
     * 重置密码
     * @param $oprId
     * @param $params
     * @return array
     * @throws \Exception
     */
    public function resetPwd($oprId, $params) {
        $rule = [
            'oldpwd|旧密码' => [
                'required'
            ],
            'newpwd|新密码' => [
                //'required', 'notEqualAttribute' => 'oldpwd', 'equalAttribute' => 'newpwd_confirm', 'regex' => '/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{6,30}/',
                'required', 'notEqualAttribute' => 'oldpwd', 'equalAttribute' => 'newpwd_confirm', 'regex' => '/^(?![^a-zA-Z]+$)(?!\D+$).{6,30}$/',
            ],
        ];
        $msg = [
            'newpwd.notEqualAttribute' => '新密码不能与旧密码相同',
            'newpwd.equalAttribute' => '两次密码输入不一致',
            'newpwd' => '请输入包含字母、数字的6-30位密码'
        ];
        $validate = new Validator($rule, $msg);
        $result = $validate->validate($params);

        if (!$result) {
            return [
                'status' => false,
                'message' => '密码格式不正确',
                'validateFailure' => $validate->getErrors()
            ];
        }

        $userModel = new UserModel();
        $userInfo = $userModel->getInfo($oprId, 'userid,username,password');
        if (empty($userInfo)) {
            return [
                'status' => false,
                'message' => '用户不存在',
            ];
        }
        if ($userModel->encryptPwd($userInfo['username'], $params['oldpwd']) != $userInfo['password']) {
            return [
                'status' => false,
                'message' => '输入旧密码不正确',
            ];
        }

        $encrtptPwd = $userModel->encryptPwd($userInfo['username'], $params['newpwd']);
        $sql = 'UPDATE User SET password=?,defaultpassword=?,updatedate=Now() WHERE userid=?';
        $var = [$encrtptPwd, 0, $oprId];

        $result = Db::update($sql, $var);

        if (!$result) {
            return [
                'status' => false,
                'message' => '操作失败',
            ];
        }

        $loginModel = new LoginModel();
        $loginModel->excluded(0, $oprId, '密码已修改，请重新登录');

        return [
            'status' => true,
            'message' => '密码修改成功，请重新登录',
        ];
    }

    public function getReportInfo($oprId, $date) {
        //操作职位数、参与项目数、服务客户数
        $sql = 'SELECT count(1) as casecount,
                       count(DISTINCT projectid) as projectcount,
                       count(DISTINCT subid) as customercount
                        FROM CaseOperator WHERE oprid=? AND status=?';
        $var = [$oprId, '01'];
        $result = Db::select($sql, $var);
        $reportList['casecount'] = $result[0]['casecount'];
        $reportList['projectcount'] = $result[0]['projectcount'];
        $reportList['customercount'] = $result[0]['customercount'];
        //剩余下载量
        $sql = 'SELECT downloadcount FROM User WHERE userid=? and status=?';
        $result = Db::selectOne($sql, $var);
        $reportList['downloadcount'] = $result['downloadcount'];
        //未完成任务
        $sql = 'SELECT count(DISTINCT taskid) as taskcount FROM TaskDetail WHERE receiver=? AND status=?';
        $result = Db::select($sql, $var);
        $reportList['taskcount'] = $result[0]['taskcount'];

        //待跟进总量
        //$reportList['waitcount'] = $this->getWaitListCount($oprId); //所有待联系
        $caseResumeApi = new CaseResumeApi();
        $timecontrol_begin = strtotime('2019-01-01');
        $timecontrol_end = strtotime('2099-12-31') + 24 * 3600 - 1;
        $search_type = 1;
        $waitflow = 1;
        //$time1 = microtime(true);
        $resultTotal = $caseResumeApi->getWaitFlowTotalNum($oprId, $search_type, $waitflow, $timecontrol_begin, $timecontrol_end);
        //$time2 = microtime(true);
        $reportList['waitcount'] = isset($resultTotal['total']) ? $resultTotal['total'] : 0;
        //$date = date('Y-m-d');

        //todo - 是否要查询当前时间之后的待跟进，不然首页左侧列表当日显示数据很可能不会变动，这样就失去了待跟进的意义
        //$todayWaitDateFrom = date('Y-m-d H:i:s');
        $todayWaitDateFrom = $date;
        $todayWaitDateTo = $date;
        //$reportList['todaywaitcount'] = $this->getWaitListCount($oprId, $todayWaitDateFrom, $todayWaitDateTo);//今天待联系
        //$reportList['todaywaitlist'] = $this->getWaitList($todayWaitDateFrom, $todayWaitDateTo, $oprId, 0, 20);

        //今日待跟进数据
        //$timecontrol_begin = strtotime(date('Y-m-d'));
        $timecontrol_begin = strtotime($date);
        $timecontrol_end = $timecontrol_begin + 24 * 3600 - 1;
        //$time1 = microtime(true);
        $postData['tagadderid'] = $oprId;
        $postData['waitflow'] = 1;
        $postData['timecontrol_begin'] = $timecontrol_begin;
        $postData['timecontrol_end'] = $timecontrol_end;
        $caseResumeList = $caseResumeApi->getCaseResumeInfoByEs($postData);
        //$time2 = microtime(true);
        $reportList['todaywaitcount'] = count($caseResumeList);//今天待联系
        $reportList['todaywaitlist'] = $this->getWaitList($oprId, $caseResumeList);

        return $reportList;
    }

    public function getMonthTasks($oprId, $date) {
        $month = date('Y-m', strtotime($date));
        $days = date('t', strtotime($date));    //本月有多少天
        $sql = "SELECT Task.taskid,Task.taskname,TaskDetail.startdate,TaskDetail.enddate,TaskDetail.status,TaskDetail.tasktype FROM Task LEFT JOIN TaskDetail ON Task.taskid=TaskDetail.taskid
                    WHERE receiver=? AND TaskDetail.startdate <= ?
                                     AND TaskDetail.enddate > ?
                                     AND (Task.status=? OR Task.status=?) AND (TaskDetail.status=? OR TaskDetail.status=?)";
        $var = [$oprId, date('Y-m-d 00:00:00', strtotime("$date + 1 month")), $date . '-01 00:00:00', '01', '02', '01', '02'];
        $result = Db::select($sql, $var);
        $tmpList = [];
        $taskList = [];
        foreach ($result as $item) {
            //开始日期在上个月，则从1号开始，否则从开始日期开始
            if (date('Y-m', strtotime($item['startdate'])) < $month) {
                $dateFrom = 1;
            } else {
                $dateFrom = date('j', strtotime($item['startdate']));
            }
            //任务结束日期在下个月，任务到本月最后一天
            if (date('Y-m', strtotime($item['enddate'])) > $month) {
                $dateEnd = $days;
            } else {
                $dateEnd = date('j', strtotime($item['enddate']));
            }
            //从开始到结束，每天都有这条任务
            for ($i = $dateFrom; $i <= $dateEnd; $i++) {
                $taskList[$i][] = $item;
            }
        }
        $tmpList['tasklist'] = $taskList;

        $caseResumeApi = new CaseResumeApi();
        $timecontrol_begin = strtotime(date('Y-m', strtotime($date)) . '-01');
        if ($days > 31) {
            $days = 31;
        }
        $timecontrol_end = $timecontrol_begin + $days * 24 * 3600 - 1;
        $search_type = 2;
        $waitflow = 1;
        //$time1 = microtime(true);
        $resultTotal = $caseResumeApi->getWaitFlowTotalNum($oprId, $search_type, $waitflow, $timecontrol_begin, $timecontrol_end);
        //$time2 = microtime(true);
        $waitCount = [];
        foreach ($resultTotal['detail'] as $item) {
            $waitCount[$item['day']] = $item['num'];
        }
        $tmpList['waitcount'] = $waitCount;
        return $tmpList;
    }

    /**
     * 待跟进人员信息列表
     * @param $dateFrom
     * @param $dateTo
     * @param $oprId
     * @param int $rowFrom
     * @param int $rowTo
     * @return array
     * @throws \Exception
     */

    public function getWaitList($oprId, $caseResumeList) {
        /*
        return [];
        $sql = 'SELECT CaseResume.caseid,resumeid,flowat,flowatstatus,timecontrol FROM CaseResume LEFT JOIN CaseOperator ON CaseResume.caseid=CaseOperator.caseid WHERE CaseResume.status=? AND CaseOperator.status=? AND waitflow=? AND oprid=?';
        $var = ['01', '01', 1, $oprId];

        if (!empty($dateFrom)) {
            $dateFrom = $dateFrom . ' 00:00:00';
            $sql .= ' AND timecontrol >= ? ';
            $var[] = $dateFrom;
        }
        if (!empty($dateTo)) {
            $dateTo = $dateTo . ' 23:59:59';
            $sql .= ' AND timecontrol <= ? ';
            $var[] = $dateTo;
        }

        $sql .= ' ORDER BY timecontrol ASC, CaseResume.id DESC';
        $result = Db::select($sql, $var, $rowFrom, $rowTo);
        */

        if (empty($caseResumeList)) {
            return [];
        }

        $result = [];
        $resumeIds = [];
        $caseIds = [];
        foreach ($caseResumeList as $item) {
            $resumeIds[] = $item['resumeid'];
            $caseIds[] = $item['caseid'];
            $result[] = [
                'caseid' => $item['caseid'],
                'resumeid' => $item['resumeid'],
                'flowat' => $item['flowat'],
                'flowatstatus' => $item['flowatstatus'],
                'timecontrol' => $item['timecontrol']
            ];
            if (count($result) == 20) {
                break;
            }
        }

        $managerModel = new Manager();
        $info = $managerModel->getManagerListByResumeId($resumeIds);
        if (empty($info)) {
            return [];
        }
        $info = $managerModel->chkDownload($oprId, $info);
        if (empty($info)) {
            return [];
        }

        $caseModel = new CaseModel();
        $caseInfo = $caseModel->getCaseListWithCustomerInfo($caseIds);
        if (empty($caseInfo)) {
            return [];
        }

        $caseFlowModel = new CaseFlow();
        $flowList = $caseFlowModel->getDefaultFlow();
        foreach ($result as &$item) {
            foreach ($info as $infoItem) {
                if ($infoItem['resumeid'] == $item['resumeid']) {
                    $item['name'] = $infoItem['cname'];
                    $item['token'] = $infoItem['token'];
                }
            }
            foreach ($caseInfo as $caseItem) {
                if ($caseItem['caseid'] == $item['caseid']) {
                    $item['subname'] = $caseItem['subname'];
                    $item['projectname'] = $caseItem['projectname'];
                    $item['projectid'] = $caseItem['projectid'];
                    $item['subid'] = $caseItem['subid'];
                    $item['casename'] = $caseItem['casename'];
                }
            }
            $item['taskname'] = $flowList[$item['flowat']]['child'][$item['flowatstatus']]['taskname'];
            $item['desc'] = $flowList[$item['flowat']]['child'][$item['flowatstatus']]['desc'];
            $item['flowatname'] = $flowList[$item['flowat']]['name'];
            $item['flowatstatusname'] = $flowList[$item['flowat']]['child'][$item['flowatstatus']]['name'];
        }

        return $result;

    }

    /**
     * 查询待跟进总数
     * @param $oprId
     * @param null $dateFrom
     * @param null $dateTo
     * @return int
     */
    public function getWaitListCount($oprId, $dateFrom = null, $dateTo = null) {
        return 0;
        $sql = 'SELECT count(1) as count FROM CaseResume LEFT JOIN CaseOperator ON CaseResume.caseid=CaseOperator.caseid WHERE CaseResume.status=? AND CaseOperator.status=? AND waitflow=? AND oprid=?';
        $var = ['01', '01', 1, $oprId];

        if (!empty($dateFrom)) {
            $dateFrom = $dateFrom . ' 00:00:00';
            $sql .= ' AND timecontrol >= ? ';
            $var[] = $dateFrom;
        }
        if (!empty($dateTo)) {
            $dateTo = $dateTo . ' 23:59:59';
            $sql .= ' AND timecontrol <= ? ';
            $var[] = $dateTo;
        }

        $resumeCount = Db::selectOne($sql, $var);
        return $resumeCount['count'] ?? 0;
    }

    public function sendPasswdEmail($userName) {
        $userName = trim($userName);
        if (is_null($userName) || $userName == '') {
            return [
                'status' => false,
                'message' => '请输入工号',
            ];
        }
        $sql = 'select email from User where username=?';
        $var = [$userName];
        $userInfo = Db::selectOne($sql, $var);
        if (empty($userInfo)) {
            return [
                'status' => false,
                'message' => '工号不存在',
            ];
        }
        if (empty($userInfo['email'])) {
            return [
                'status' => false,
                'message' => '邮箱不存在',
            ];
        }
        $email = $userInfo['email'];
        $timeStamp = time();
        $uniqueCode = md5(md5($userName . $email . $timeStamp));
        $result = $this->sendVerifyEmail($userName, $email, $uniqueCode);
        //md5码保存到redis,24小时内有效
        $redisClient = Redis::connect('forgetpasswd_md5');
        $keyValue = 'forgetpasswd:username:' . $userName;
        $redisClient->set($keyValue, $uniqueCode, 86400);

        return [
            'status' => true,
            'message' => $result ? '发送成功' : '发送失败',
            'info' => $result ? '已向您的' . $email . '邮箱发送修改密码链接，请注意查收' : '邮件发送失败，请重试'
        ];
    }

    private function sendVerifyEmail($username, $email, $uniqueCode) {
        $mail = new Mailer();
        $status = true;
        try {
            $mail->isJobsmail(true);
            $mail->setFrom($mail->defaultSender['noreplay']['email'], $mail->defaultSender['noreplay']['name']);
            $mail->addAddress($email);
            $mail->isHTML(true);
            $mail->Subject = 'RPO系统找回密码通知';
            $mail->Body = '请登录' . config('app.setnewpwd', '') . '?username=' . $username . '&verify=' . $uniqueCode . ' 修改您的密码(本链接24小时内有效)。<br/>';
            $mail->setJobsmailFlag(config('mail.flag.common', 0));
            $mail->send();
        } catch (\Exception $e) {
            Log::error('修改' . $username . '用户密码邮件发送失败: ', [$mail->ErrorInfo]);
            $status = false;
        }
        return $status;
    }

    public function chkVerify($verify, $userName) {
        $redisClient = Redis::connect('forgetpasswd_md5');
        $keyValue = 'forgetpasswd:username:' . $userName;
        $chkVerify = $redisClient->get($keyValue);

        if (empty($chkVerify)) {
            return [
                'status' => false,
                'message' => '该链接已失效，请重试'
            ];
        }
        if ($chkVerify != $verify) {
            Log::error('用户' . $userName . '找回密码验证失败,验证md5:' . $chkVerify . '获取md5:' . $verify);
            return [
                'status' => false,
                'message' => '身份验证失败，请重试'
            ];
        }
        return [
            'status' => true,
            'message' => '验证成功'
        ];
    }

    public function forgetPasswd($username, $newPasswd, $confirmPasswd) {
        $rule = [
            'username|工号' => [
                'required'
            ],
            'newpwd|新密码' => [
                'required', 'regex' => '/^(?![^a-zA-Z]+$)(?!\D+$).{6,30}$/',
            ],
            'newpwd_confirm|确认密码' => [
                'required', 'equalAttribute' => 'newpwd',
            ]
        ];
        $msg = [
            'newpwd_confirm.equalAttribute' => '两次密码输入不一致',
            'newpwd' => '请输入包含字母、数字的6-30位密码'
        ];
        $validate = new Validator($rule, $msg);
        $result = $validate->validate([
            'username' => $username,
            'newpwd' => $newPasswd,
            'newpwd_confirm' => $confirmPasswd
        ]);

        if (!$result) {
            return [
                'status' => false,
                'message' => '密码格式不正确',
                'validateFailure' => $validate->getErrors()
            ];
        }

        $userModel = new UserModel();
        $sql = 'select userid,username from User where username=?';
        $var = [$username];
        $userInfo = Db::selectOne($sql, $var);
        if (empty($userInfo)) {
            return [
                'status' => false,
                'message' => '工号不存在',
            ];
        }
        $encrtptPwd = $userModel->encryptPwd($userInfo['username'], $newPasswd);
        $sql = 'UPDATE User SET password=?,defaultpassword=?,updatedate=Now() WHERE username=?';
        $var = [$encrtptPwd, 0, $username];

        $result = Db::update($sql, $var);

        if (!$result) {
            return [
                'status' => false,
                'message' => '操作失败',
            ];
        }
        //修改成功，删掉redis中的缓存数据
        $redisClient = Redis::connect('forgetpasswd_md5');
        $keyValue = 'forgetpasswd:username:' . $username;
        $redisClient->del($keyValue);

        return [
            'status' => true,
            'message' => '密码修改成功',
        ];


    }

    /**
     * 发送手机验证码
     * @param $userId
     * @param $mobilePhone
     * @param $action
     * @param $smsContent
     * @return array
     * @throws \Exception
     */
    public function sendMpVerifyCode($userId, $mobilePhone, $action, $smsContent) {
        //获取用户信息并保存验证码
        $userModel = new UserModel();
        $userInfo = $userModel->getInfoWithRoleByPhone($mobilePhone);
        if (!empty($userInfo)) {
            if ($userInfo['userid'] != $userId) {
                return ['status' => -2, 'message' => '该手机号已被其他账号绑定'];
            }
            return ['status' => -1, 'message' => '您已绑定该手机，无需重复绑定'];
        }
        $verifyCode = Captcha::generate('phone', $userId . '_' . $mobilePhone . $action);
        if ($verifyCode['error'] != 0) {
            return ['status' => -10, 'message' => '发送验证码出现错误', 'error' => $verifyCode];
        }

        //发送验证码
        $sms = new Sms();
        $channel = config('app.sms.channel.account');
        $smsContent = str_replace('##code##', $verifyCode['code'], $smsContent);
        $smsContent = str_replace('##expire##', floor($verifyCode['expire'] / 60), $smsContent);
        $result = $sms->send($mobilePhone, $smsContent, $channel);
        if ($result) {
            return ['status' => 0, 'message' => '短信发送成功'];
        }
        return ['status' => -3, 'message' => '短信发送失败'];
    }

    /**
     * 绑定手机号
     * @param $userId
     * @param $telPhone
     * @param $verifyCode
     * @return array
     */
    public function bindPhone($userId, $telPhone, $verifyCode) {
        $userModel = new UserModel();
        $userInfo = $userModel->getInfoWithRoleByPhone($telPhone);

        if (!empty($userInfo)) {
            if ($userInfo['userid'] != $userId) {
                return ['status' => -2, 'message' => '该手机已被其他账号绑定',];
            }
            return ['status' => 0, 'message' => '绑定成功',];
        }

        //校验短信验证码
        $result = Captcha::check('phone', $userId . '_' . $telPhone . '_mpbind', $verifyCode);
        if (!$result) {
            return [
                'status' => -4,
                'message' => '验证码错误',
                'errorFields' => ['phoneverify' => '手机验证码错误']
            ];
        }

        $sql = 'update User set mobilephone=?,mobileauth=?,updatedate=Now() where userid=?';
        $var = [$telPhone, 1, $userId];
        $result = Db::update($sql, $var);
        if (!$result) {
            Log::error('用户id:' . $userInfo['userid'] . '绑定手机失败');
            return ['status' => -5, 'message' => '系统繁忙，请稍后再试',];
        }
        //手机号修改之后，需要更新登录token刷新登录状态
        $authToken = UserAuth::getAuthToken();
        $loginModel = new LoginModel();
        $newAuthToken = $loginModel->replaceLogin($authToken);
        if(!$newAuthToken['status']){
            return ['status' => -10, 'message' => '系统异常，请重新登录',];
        }
        return ['status' => 0, 'message' => '绑定成功', 'newtoken' => $newAuthToken['authtoken']];
    }
}